package ru.compft.web.utils;

//import org.springframework.web.context.WebApplicationContext;
//import org.springframework.web.jsf.FacesContextUtils;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import ru.compft.common.utils.GlobalConstants;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseId;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * User: VVasiliev
 * Date: 22.08.2011
 * Time: 16:57:37
 * <p/>
 * Утилиты для работы с Faces-объектами
 */
public class FacesUtils {

    private static final String SERVICE_LOCATOR_BEAN_NAME = "serviceLocator";

    /**
     * Get servlet context.
     *
     * @return the servlet context
     */
    public static ServletContext getServletContext() {
        return (ServletContext) getExternalContext().getContext();
    }

    public static void redirectToUrl(String url) throws IOException {
        getExternalContext().redirect(getContextPath() + url);
    }

    public static void dispatchToUrl(String url) throws IOException, ServletException {
        final ExternalContext context = getExternalContext();

        final ServletRequest servletRequest = (ServletRequest) context.getRequest();
        final ServletResponse servletResponse = (ServletResponse) context.getResponse();

        if (servletRequest != null && servletResponse != null) {
            final RequestDispatcher dispatcher = servletRequest.getRequestDispatcher(url);

            if (dispatcher != null) {
                dispatcher.forward(servletRequest, servletResponse);
                FacesContext.getCurrentInstance().responseComplete();
            }
        }
    }

    public static String getContextPath() {
        final String contextPath = getServletContext().getContextPath();
        return GlobalConstants.SLASH.equals(contextPath) ? "" : contextPath;
    }

    public static ExternalContext getExternalContext() {
        return FacesContext.getCurrentInstance().getExternalContext();
    }

    public static String getQueryString() {
        return ((HttpServletRequest) getExternalContext().getRequest()).getQueryString();
    }

    public static String getRequestURI() {
        return ((HttpServletRequest) getExternalContext().getRequest()).getRequestURI();
    }

    /**
     * Given a bean name, get the backing bean associated with it.  Even though spring is in use
     * in this sample application - we use the JSF context.  That is because we don't need to make
     * anything more complicated than it already is.
     *
     * @param beanName String name of the bean: like breadcrumbBean
     * @return Object to be cast to bean type
     */
    public static Object getBackingBean(String beanName) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
        ValueExpression valueExpression =
                expressionFactory.createValueExpression(elContext, convertToElSyntax(beanName), Object.class);
        return valueExpression.getValue(elContext);
    }

    /**
     * Получаем bean из контекста Spring
     *
     * @param name
     * @return
     */
    public static Object getSpringBean(String name) {
        final WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(FacesUtils.getServletContext());
        return ctx.getBean(name);
    }

    /**
     * Add error message to a specific client.
     *
     * @param clientId the client id
     * @param msg      the error message
     */
    public static void addErrorMessage(String clientId, String msg) {
        FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
    }

    /**
     * Add warning message to a specific client.
     *
     * @param clientId the client id
     * @param msg      the information message
     */
    public static void addWarnMessage(String clientId, String msg) {
        FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_WARN, msg, msg));
    }

    /**
     * Add information message to a specific client.
     *
     * @param clientId the client id
     * @param msg      the information message
     */
    public static void addInfoMessage(String clientId, String msg) {
        FacesContext.getCurrentInstance().addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
    }

    private static String convertToElSyntax(String value) {
        return new StringBuffer("#{").append(value).append("}").toString();
    }

    /**
     * Method to return the value specified via an f:attribute component
     *
     * @param event of the parent that had the f:attribute
     * @param name  of the param
     * @return the Object value, which may be null if the attribute wasn't found
     */
    public static Object getFAttribute(ActionEvent event, String name) {
        return event.getComponent().getAttributes().get(name);
    }

    public static PhaseId getCurrentPhaseId() {
        return FacesContext.getCurrentInstance().getCurrentPhaseId();
    }
//    public static ServiceLocator getServiceLocator() {
//        final FacesContext context = FacesContext.getCurrentInstance();
//        final WebApplicationContext applicationContext = FacesContextUtils.getWebApplicationContext(context);
//
//        return (ServiceLocator) applicationContext.getBean(SERVICE_LOCATOR_BEAN_NAME);
//    }
//
//    public static String getRealPath(String fileName) {
//        final FacesContext context = FacesContext.getCurrentInstance();
//        final ServletContext servletContext = (ServletContext) context.getExternalContext().getContext();
//        return servletContext.getRealPath(fileName);
//    }
}

